﻿#pragma once
#include "XyNet/Global.h"

// 因为begin和end在移除操作后可能会失效，不同容器要不同处理
// 为保证迭代器透明度，不提供这两个函数实现
// 另外，无法保证所有容器返回同一类型的begin和end

namespace XyNet
{
	template <typename ElementType> class IteratorImpl;
	template <typename ContainerType, typename ElementType> class ContainerIteratorImpl;
	template <typename MapType, typename ElementType> class MapKeyIteratorImpl;
	template <typename MapType, typename ElementType> class MapValueIteratorImpl;

	/// 常量迭代器
	template <typename ElementType>
	class ConstIterator
	{
	public:
		ConstIterator() {}

		ConstIterator(shared_ptr<IteratorImpl<ElementType>> impl) : _impl(impl) {}

		ConstIterator(const ConstIterator<ElementType>& other)
		{
			_impl = other._impl->clone();
		}

		inline ConstIterator& operator=(const ConstIterator<ElementType>& other)
		{
			_impl = other._impl->clone();
			return *this;
		}

		/// 移动到下一个迭代元素，返回是否可获取当前迭代元素
		inline bool moveNext() const
		{
			return _impl->moveNext();
		}

		/// 获取当前迭代元素（不能返回ElementType*，会和shared_ptr冲突）
		inline ElementType getCurrent() const
		{
			return _impl->getCurrent();
		}

	public:
		/// 生成容器迭代器
		template <typename ContainerType>
		inline static ConstIterator<ElementType> makeContainerIterator(const ContainerType* container)
		{
			return ConstIterator<ElementType>(
				make_shared<ContainerIteratorImpl<ContainerType, ElementType>>(container));
		}

		/// 生成映射键迭代器
		template <typename MapType>
		inline static ConstIterator<ElementType> makeMapKeyIterator(const MapType* map)
		{
			return ConstIterator<ElementType>(
				make_shared<MapKeyIteratorImpl<MapType, ElementType>>(map));
		}

		/// 生成映射值迭代器
		template <typename MapType>
		inline static ConstIterator<ElementType> makeMapValueIterator(const MapType* map)
		{
			return ConstIterator<ElementType>(
				make_shared<MapValueIteratorImpl<MapType, ElementType>>(map));
		}

	protected:
		shared_ptr<IteratorImpl<ElementType>> _impl;
	};

	//////////////////////////////////////////////////////////////////////////

	/// 迭代器
	template <typename ElementType>
	class Iterator : public ConstIterator<ElementType>
	{
	public:
		Iterator() {}

		Iterator(shared_ptr<IteratorImpl<ElementType>> impl) : ConstIterator<ElementType>(impl) {}

		Iterator(const Iterator<ElementType>& other)
		{
			_impl = other._impl->clone();
		}

		inline Iterator& operator=(const Iterator<ElementType>& other)
		{
			_impl = other._impl->clone();
			return *this;
		}

		/// 移除当前迭代元素
		inline void removeCurrent()
		{
			_impl->removeCurrent();
		}

	public:
		/// 生成容器迭代器
		template <typename ContainerType>
		inline static Iterator<ElementType> makeContainerIterator(ContainerType* container)
		{
			return Iterator<ElementType>(
				make_shared<ContainerIteratorImpl<ContainerType, ElementType>>(container));
		}

		/// 生成映射键迭代器
		template <typename MapType>
		inline static Iterator<ElementType> makeMapKeyIterator(MapType* map)
		{
			return Iterator<ElementType>(
				make_shared<MapKeyIteratorImpl<MapType, ElementType>>(map));
		}

		/// 生成映射值迭代器
		template <typename MapType>
		inline static Iterator<ElementType> makeMapValueIterator(MapType* map)
		{
			return Iterator<ElementType>(
				make_shared<MapValueIteratorImpl<MapType, ElementType>>(map));
		}

	private:
		using ConstIterator<ElementType>::_impl;
	};

	//////////////////////////////////////////////////////////////////////////

	/// 迭代器实现（考虑到set、map的元素不应该被修改，所以next必须加上const）
	template <typename ElementType>
	class IteratorImpl
	{
	public:
		virtual ~IteratorImpl() {}

		/// 克隆
		virtual shared_ptr<IteratorImpl<ElementType>> clone() const = 0;

		/// 移动到下一个迭代元素，返回是否可获取当前迭代元素
		virtual bool moveNext() const = 0;
		/// 获取当前迭代元素（不能返回ElementType*，会和shared_ptr冲突）
		virtual ElementType getCurrent() const = 0;
		/// 移除当前迭代元素
		virtual void removeCurrent() { assert(false); }
	};

	//////////////////////////////////////////////////////////////////////////

	/// 范围容器迭代器（只要是含begin()和end()的对象都可以用）
	template <typename RangeType, typename ElementType = const typename RangeType::value_type&>
	class RangeIteratorImpl : public IteratorImpl<ElementType>
	{
	protected:
		RangeIteratorImpl(const RangeType* range)
			: IteratorImpl<ElementType>(), _range(const_cast<RangeType*>(range))
		{
			_current = _range->end();
			_next = _range->begin();
		}

		virtual ~RangeIteratorImpl() {}

		virtual bool moveNext() const override
		{
			if (_next != _range->end())
			{
				_current = _next++;
				return true;
			}
			else
			{
				_current = _next;	// 将_current设为无效
				return false;
			}
		}

	protected:
		RangeType* _range;
		mutable typename RangeType::iterator _current;
		mutable typename RangeType::iterator _next;
	};

	//////////////////////////////////////////////////////////////////////////

	/// 可移除的范围容器迭代器
	template <typename RangeType,
		typename ElementType = const typename RangeType::value_type&>
		class RemovableRangeIteratorImpl : public RangeIteratorImpl<RangeType, ElementType>
	{
	protected:
		RemovableRangeIteratorImpl(const RangeType* range)
			: RangeIteratorImpl<RangeType, ElementType>(range) {}

		virtual ~RemovableRangeIteratorImpl() {}

		virtual void removeCurrent() override
		{
			assert(_current != _range->end());
			_next = _range->erase(_current);	// 迭代器有可能失效，需要重新获取
			_current = _range->end();	// 当前迭代器设为end，避免多次调用removeCurrent()
		}

	protected:
		using RangeIteratorImpl<RangeType, ElementType>::_range;
		using RangeIteratorImpl<RangeType, ElementType>::_current;
		using RangeIteratorImpl<RangeType, ElementType>::_next;
	};

	//////////////////////////////////////////////////////////////////////////

	/// 容器迭代器
	template <typename ContainerType,
		typename ElementType = const typename ContainerType::value_type&>
		class ContainerIteratorImpl : public RemovableRangeIteratorImpl<ContainerType, ElementType>
	{
	public:
		ContainerIteratorImpl(const ContainerType* container)
			: RemovableRangeIteratorImpl<ContainerType, ElementType>(container) {}

		virtual ~ContainerIteratorImpl() {}

	protected:
		virtual shared_ptr<IteratorImpl<ElementType>> clone() const override
		{
			return make_shared<ContainerIteratorImpl<ContainerType, ElementType>>(*this);
		}

		virtual ElementType getCurrent() const override
		{
			assert(_current != _range->end());
			return *_current;
		}

	protected:
		using RemovableRangeIteratorImpl<ContainerType, ElementType>::_range;
		using RemovableRangeIteratorImpl<ContainerType, ElementType>::_current;
	};

	//////////////////////////////////////////////////////////////////////////

	/// map键迭代器
	template <typename MapType,
		typename ElementType = const typename MapType::key_type&>
		class MapKeyIteratorImpl : public RemovableRangeIteratorImpl<MapType, ElementType>
	{
	public:
		MapKeyIteratorImpl(const MapType* map)
			: RemovableRangeIteratorImpl<MapType, ElementType>(map) {}

		virtual ~MapKeyIteratorImpl() {}

	protected:
		virtual shared_ptr<IteratorImpl<ElementType>> clone() const override
		{
			return make_shared<MapKeyIteratorImpl<MapType, ElementType>>(*this);
		}

		virtual ElementType getCurrent() const override
		{
			assert(_current != _range->end());
			return _current->first;
		}

	protected:
		using RemovableRangeIteratorImpl<MapType, ElementType>::_range;
		using RemovableRangeIteratorImpl<MapType, ElementType>::_current;
	};

	//////////////////////////////////////////////////////////////////////////

	/// map值迭代器
	template <typename MapType,
		typename ElementType = const typename MapType::mapped_type&>
		class MapValueIteratorImpl : public RemovableRangeIteratorImpl<MapType, ElementType>
	{
	public:
		MapValueIteratorImpl(const MapType* map)
			: RemovableRangeIteratorImpl<MapType, ElementType>(map) {}

		virtual ~MapValueIteratorImpl() {}

	protected:
		virtual shared_ptr<IteratorImpl<ElementType>> clone() const override
		{
			return make_shared<MapValueIteratorImpl<MapType, ElementType>>(*this);
		}

		virtual ElementType getCurrent() const override
		{
			assert(_current != _range->end());
			return _current->second;
		}

	protected:
		using RemovableRangeIteratorImpl<MapType, ElementType>::_range;
		using RemovableRangeIteratorImpl<MapType, ElementType>::_current;
	};
}